import os
import windnd
import _thread
from tkinter import *
from tkinter.scrolledtext import ScrolledText
import numpy as np
from math import e
import matplotlib.pyplot as plt


busy_now = False


def get_list(data):
    if type(data) == type(b'0'):
        return list(data)
    elif type(data) == type('0'):
        return list(data.encode())
    elif type(data) != type([0]):
        return None


def entropy(labels, base=None):
    value, counts = np.unique(labels, return_counts=True)
    norm_counts = counts / counts.sum()
    base = e if base is None else base
    return -(norm_counts * np.log(norm_counts)/np.log(base)).sum()


def entropy_sliding_window(labels, windowSize, base=None):
    if len(labels) < windowSize:
        return None
    interval = int(windowSize / 3)
    lsize = len(labels) - windowSize
    lx = []
    ly = []
    start = 0
    while start <= lsize:
        lx.append(start)
        ly.append(entropy(labels[start : start + windowSize], base))
        start += interval
    return lx, ly


def plot_entropy(x, y):
    plt.figure()
    plt.ylim([0, 8])
    plt.grid(alpha=0.1)
    plt.plot(x, y)
    plt.show()


def thread_work(filelist):
    global busy_now
    res = ''
    for f in filelist:
        with open(f, "rb") as file:
            data = file.read()
            ldata = get_list(data)
            entropyVal = entropy(ldata, 2)
            res += f + '\n'
            res += '    entropy: ' + str(entropyVal) + '\n\n'
            if len(filelist) == 1 and len(data) > 1024 and len(data) < 1024*1024*64:
                x, y = entropy_sliding_window(ldata, 256, 2)
                plot_entropy(x, y)
    showMsg(res)
    busy_now = False


def showMsg(txt):
    Edit1.configure(state='normal')
    Edit1.delete(1.0, END)
    Edit1.insert(1.0, '\n' + txt)
    Edit1.configure(state='disabled')
    

def dragged_files(files):
    global busy_now

    if busy_now:
        return

    filelist = []
    for file in files:
        f = file.decode('gbk')
        if not os.path.isfile(f):
            showMsg('您选择的对象不是文件！')
            return
        filelist.append(f)

    busy_now = True
    showMsg('计算中......')
    _thread.start_new_thread(thread_work, (filelist, ))


root = Tk()
root.title('Drag Entropy Tool')
windnd.hook_dropfiles(root, func=dragged_files)

Edit1 = ScrolledText(root, width=80, height=20, padx=8, pady=8)
Edit1.grid(row=1, column=1)
showMsg('请拖放文件......')

root.mainloop()
